package com.irdstudio.efp.flow.executor;

import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.irdstudio.efp.flow.common.constance.FlowConstance;
import com.irdstudio.efp.flow.common.service.Executor;
import com.irdstudio.efp.flow.common.vo.EngineVO;
import com.irdstudio.efp.flow.enumeration.PluginTypeBean;
import com.irdstudio.efp.flow.service.facade.BizFlowTaskParamService;
import com.irdstudio.efp.flow.service.facade.BizPluginServiceService;
import com.irdstudio.efp.flow.service.facade.InstFlowTaskService;
import com.irdstudio.efp.flow.service.vo.InstFlowTaskVO;
import com.irdstudio.basic.framework.core.constant.FlowExceptionType;
import com.irdstudio.basic.framework.core.exception.FlowException;
import com.irdstudio.basic.framework.core.exception.PauseException;
import com.irdstudio.basic.framework.core.exception.TerminateException;
import com.irdstudio.basic.framework.core.util.SpringContextUtils;

/**
 * 
 * 任务执行器
 * 
 * @author Cytus_
 * @since 2018年5月7日 下午3:53:33
 * @version 1.0
 *
 */
@Service("taskExecutor")
public class TaskExecutor implements Executor {

	private static Logger logger = LoggerFactory.getLogger(TaskExecutor.class);
	
	@Autowired
	@Qualifier("bizPluginServiceService")
	private BizPluginServiceService bizPluginServiceService;
	
	@Autowired
	@Qualifier("instFlowTaskService")
	private InstFlowTaskService instFlowTaskService;
	
	@Autowired
	@Qualifier("bizFlowTaskParamService")
	private BizFlowTaskParamService bizFlowTaskParamService;
	
	public EngineVO execute(EngineVO evo) throws FlowException {
		
		evo.setTaskExecuteStatus(FlowConstance.TASK_STATUS_RUNNING);
		logger.info("节点实例号:"+ evo.getNodeInstanceId() +", 任务编号："+ evo.getTaskId() +"执行当前任务开始......");
		InstFlowTaskVO queryInfo = new InstFlowTaskVO();
		queryInfo.setTaskId(evo.getTaskId());
		queryInfo.setInstNodeId(evo.getNodeInstanceId());
		InstFlowTaskVO task = instFlowTaskService.queryTaskByNodeTaskId(queryInfo);
		if (Objects.isNull(task)) {
			logger.error("节点实例号:"+ evo.getNodeInstanceId() +", 任务编号："+ evo.getTaskId() +"尚未进行配置!");
			throw new FlowException("节点实例号:"+ evo.getNodeInstanceId() +", 任务编号："+ evo.getTaskId() +"尚未进行配置!");
		}
		
		updateTaskStateByNodeTaskId(evo.getNodeInstanceId(), evo.getTaskId(), evo.getTaskExecuteStatus(), evo.getErrorMessage());
		try {
			PluginTaskExecutor flowTask = (PluginTaskExecutor) SpringContextUtils.getBean(PluginTypeBean.getPluginTypeBeanValue(task.getBizPluginType()));
			evo = flowTask.doTask(evo, task);
		} catch (TerminateException e) {
			logger.warn("节点实例号:"+ evo.getNodeInstanceId() +", 任务编号："+ evo.getTaskId() +"执行当前任务出现终止提示, cause by:"+ e.getMessage());
			evo.setErrorMessage(e.getMessage());
			evo.setTaskExecuteStatus(FlowConstance.TASK_STATUS_TERMINATE);
			if (e.getFlowExceptionType().isHighLevel(FlowExceptionType.TASK)) {
			    throw e;
			}
		} catch (PauseException e) {
			logger.warn("节点实例号:"+ evo.getNodeInstanceId() +", 任务编号："+ evo.getTaskId() +"执行当前任务出现暂停提示, cause by:"+ e.getMessage());
			evo.setTaskExecuteStatus(FlowConstance.TASK_STATUS_PAUSE);
			evo.setErrorMessage(e.getMessage());
		} catch (Exception e) {
			logger.error("节点实例号:"+ evo.getNodeInstanceId() +", 任务编号："+ evo.getTaskId() +"执行当前任务出现异常!", e);
			if (!(e instanceof TerminateException)) {
			    evo.setTaskExecuteStatus(FlowConstance.TASK_STATUS_EXCEPTION);
			    evo.setErrorMessage(e.getMessage());
			}
		} finally {
			updateTaskStateByNodeTaskId(evo.getNodeInstanceId(), evo.getTaskId(), evo.getTaskExecuteStatus(), evo.getErrorMessage());
		}
		logger.info("节点实例号:"+ evo.getNodeInstanceId() +", 任务编号："+ evo.getTaskId() +"执行当前任务结束......");
		return evo;
	}
	
	/**
	 * 更新任务状态
	 * @param instNodeId
	 * @param taskId
	 * @param taskStatus
	 * @return
	 */
	private int updateTaskStateByNodeTaskId(String instNodeId, String taskId, String taskStatus, String errorMsg) {
		InstFlowTaskVO task = new InstFlowTaskVO();
		task.setInstNodeId(instNodeId);
		task.setTaskId(taskId);
		task.setTaskState(taskStatus);
		task.setErrorMsg(errorMsg);
		int record = this.instFlowTaskService.updateTaskStateByNodeTaskId(task);
		logger.info("当前节点实例:"+ instNodeId +", 任务编号:"+ taskId +", 更新任务状态为："+ taskStatus +"结束");
		return record;
	}

}
